package com.biodiv.community.manager.current;

import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.util.Map;
import java.util.concurrent.*;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;

/**
 * @author tianquan
 */
@Slf4j
@Data
@Component
public class ThreadPoolManager {

    private final ThreadPoolExecutor threadPool;
    private final OperatingSystemMXBean osBean;

    public void execute(Runnable task) {
        // 获取当前线程的 MDC 上下文
        Map<String, String> contextMap = MDC.getCopyOfContextMap();
        threadPool.execute(() -> {
            try {
                // 在子线程中恢复 MDC 上下文
                if (contextMap != null) {
                    MDC.setContextMap(contextMap);
                }
                task.run();
            } finally {
                // 清理上下文
                MDC.clear();
            }
        });
    }

    public ThreadPoolManager() {
        this.osBean = ManagementFactory.getOperatingSystemMXBean();

        // 分析硬件资源并计算合适的线程池参数
        int corePoolSize = calculateCorePoolSize();
        int maxPoolSize = calculateMaxPoolSize();
        long keepAliveTime = calculateKeepAliveTime();
        int queueCapacity = calculateQueueCapacity();

        // 创建线程池
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(queueCapacity);
        ThreadFactory threadFactory = Executors.defaultThreadFactory();

        // 自定义拒绝策略，使用日志记录代替 System.err
        RejectedExecutionHandler rejectionHandler = (r, executor) -> {
            log.info("Task rejected: {}", r.toString());
        };

        threadPool = new ThreadPoolExecutor(
                corePoolSize,
                maxPoolSize,
                keepAliveTime,
                TimeUnit.SECONDS,
                workQueue,
                threadFactory,
                rejectionHandler
        );

        // 配置线程池的其他优化参数
        threadPool.allowCoreThreadTimeOut(true);
        log.info("HardwareAwareThreadPool initialized with: core={}, max={}, queue={}", corePoolSize, maxPoolSize, queueCapacity);
    }

    // 根据CPU核心数计算核心线程数
    private int calculateCorePoolSize() {
        int cpuCores = Runtime.getRuntime().availableProcessors();
        // 对于IO密集型任务，核心线程数可以设置为CPU核心数的2倍
        int coreSize = cpuCores * 2;
        log.info("Calculated core pool size: {}", coreSize);
        return coreSize;
    }

    // 计算最大线程数
    private int calculateMaxPoolSize() {
        int coreSize = calculateCorePoolSize();
        // 最大线程数设置为核心线程数的1.5倍
        int maxSize = (int) (coreSize * 1.5);
        log.info("Calculated max pool size: {}", maxSize);
        return maxSize;
    }

    // 计算线程空闲时间
    private long calculateKeepAliveTime() {
        // 对于IO密集型应用，设置60秒的空闲时间
        return 60L;
    }

    // 计算任务队列容量
    private int calculateQueueCapacity() {
        try {
            // 使用更健壮的方法获取系统内存信息
            long freePhysicalMemory = getSystemMemoryInfo("getFreePhysicalMemorySize");
            long totalPhysicalMemory = getSystemMemoryInfo("getTotalPhysicalMemorySize");

            // 防止除以零错误
            if (totalPhysicalMemory <= 0) {
                log.info("Failed to get total physical memory, using default queue capacity");
                return 1000;
            }

            // 根据可用内存百分比动态调整队列大小
            double memoryUsageRatio = (double) freePhysicalMemory / totalPhysicalMemory;
            int baseCapacity = 1000;

            // 内存充足时增加队列容量，内存紧张时减少队列容量
            int calculatedCapacity = (int) (baseCapacity * (1.0 + memoryUsageRatio));

            // 限制最大队列容量为5000，防止内存溢出
            return Math.min(5000, calculatedCapacity);
        } catch (Exception e) {
            log.info("Failed to calculate queue capacity using system memory, using default", e);
            return 1000; // 默认队列容量
        }
    }

    // 使用反射获取系统内存信息的通用方法
    private long getSystemMemoryInfo(String methodName) {
        try {
            java.lang.reflect.Method method = osBean.getClass().getMethod(methodName);
            return (Long) method.invoke(osBean);
        } catch (Exception e) {
            log.info("Failed to invoke method: " + methodName, e);
            return -1;
        }
    }

    // 关闭线程池
    public void shutdown() {
        log.info("Shutting down thread pool");
        threadPool.shutdown();
        try {
            if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {
                log.warn("Thread pool did not terminate within 60 seconds, forcing shutdown");
                threadPool.shutdownNow();
            }
        } catch (InterruptedException e) {
            log.warn("Interrupted while waiting for thread pool termination, forcing shutdown");
            threadPool.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    // 打印当前硬件信息和线程池配置
    public void printConfiguration() {
        System.out.println("===== 硬件信息 =====");
        System.out.println("CPU核心数: " + Runtime.getRuntime().availableProcessors());
        System.out.println("JVM总内存: " + formatMemory(Runtime.getRuntime().totalMemory()));
        System.out.println("JVM空闲内存: " + formatMemory(Runtime.getRuntime().freeMemory()));

        try {
            System.out.println("系统总内存: " + formatMemory(getSystemMemoryInfo("getTotalPhysicalMemorySize")));
            System.out.println("系统可用内存: " + formatMemory(getSystemMemoryInfo("getFreePhysicalMemorySize")));
        } catch (Exception e) {
            System.out.println("无法获取系统内存信息: " + e.getMessage());
        }

        System.out.println("\n===== 线程池配置 =====");
        System.out.println("核心线程数: " + threadPool.getCorePoolSize());
        System.out.println("最大线程数: " + threadPool.getMaximumPoolSize());
        System.out.println("线程空闲时间: " + threadPool.getKeepAliveTime(TimeUnit.SECONDS) + " 秒");
        System.out.println("任务队列容量: " + threadPool.getQueue().remainingCapacity());
        System.out.println("当前活跃线程数: " + threadPool.getActiveCount());
    }

    // 格式化内存大小显示
    private String formatMemory(long bytes) {
        if (bytes < 0) {
            return "未知";
        }

        if (bytes < 1024) {
            return bytes + " B";
        }
        if (bytes < 1024 * 1024) {
            return String.format("%.2f KB", bytes / 1024.0);
        }
        if (bytes < 1024 * 1024 * 1024) {
            return String.format("%.2f MB", bytes / (1024.0 * 1024));
        }
        return String.format("%.2f GB", bytes / (1024.0 * 1024 * 1024));
    }

    // 示例：如何使用这个硬件感知的线程池
    public static void main(String[] args) {
        ThreadPoolManager poolManager = new ThreadPoolManager();
        ThreadPoolExecutor executor = poolManager.getThreadPool();

        // 打印配置信息
        poolManager.printConfiguration();

        // 提交一些示例任务
        for (int i = 0; i < 20; i++) {
            final int taskId = i;
            executor.submit(() -> {
                System.out.println("任务 " + taskId + " 在线程 " + Thread.currentThread().getName() + " 上执行");
                try {
                    Thread.sleep(1000); // 模拟任务执行时间
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        // 关闭线程池
        poolManager.shutdown();
    }

}